package com.tuniu.agents.tools.flights.domestic.oneway;

import com.fasterxml.jackson.annotation.JsonClassDescription;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyDescription;
import com.tuniu.agents.advisor.ChatEnvironmentMemory;
import com.tuniu.agents.message.MessageSender;
import com.tuniu.agents.message.ToolLogger;
import com.tuniu.agents.message.ToolLoggerInfo;
import com.tuniu.agents.tools.flights.FlightProperties;
import com.tuniu.agents.tools.flights.enums.FlightToolEnum;
import com.tuniu.agents.tools.flights.utils.AirportQueryUtils;
import com.tuniu.agents.tools.flights.utils.FlightMessageUtils;
import com.tuniu.agents.util.HttpManager;
import com.tuniu.agents.util.I18nUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.model.ToolContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;

public class FlightTimeQueryTool implements BiFunction<FlightTimeQueryTool.Request, ToolContext, FlightLowPriceQueryTool.Response>, ToolLogger {

    public static final String TOOLNAME = "FlightTimeQueryTool";

    private static final Logger logger = LoggerFactory.getLogger(FlightTimeQueryTool.class);

    private final String flightTimeQueryToolUrl;
    private final String flightNearGoQueryToolUrl;
    private final String flightNearBackQueryToolUrl;

    private final String approachApiUrl;

    @Autowired(required = false)
    private ChatEnvironmentMemory chatEnvironmentMemory;

    @Autowired
    private HttpManager httpManager;

    @Autowired
    private MessageSender messageSender;

    public FlightTimeQueryTool(FlightProperties properties) {
        assert StringUtils.hasText(properties.getFlightTransferQueryToolUrl());
        this.flightTimeQueryToolUrl = properties.getFlightTimeQueryToolUrl();
        this.flightNearGoQueryToolUrl = properties.getFlightNearGoQueryToolUrl();
        this.flightNearBackQueryToolUrl = properties.getFlightNearBackQueryToolUrl();

        this.approachApiUrl = properties.getApproachQueryToolUrl();
    }

    @ToolLoggerInfo(beanName = TOOLNAME)
    @Override
    public FlightLowPriceQueryTool.Response apply(Request request, ToolContext toolContext) {
        Map<String, Object> map = toolContext.getContext();
        String conversationId = (String) map.get("conversation_id");
        FlightLowPriceQueryTool.Response post = null;
        try {
            // 查询当前城市是否有机场
            List<String> cityList = new ArrayList<>();
            cityList.add(request.departureCityName);
            cityList.add(request.arrivalCityName);
            Map<String, Boolean> mapCity = AirportQueryUtils.batchCheckAirports(httpManager, approachApiUrl, cityList);

            String[] loadingStr = FlightToolEnum.FLIGHT_TIME_TOOL_LIST.getInner().split(",");
            // 调用工具
            if (mapCity.get(request.departureCityName)) {
                messageSender.send(conversationId, I18nUtil.getMessage(conversationId,loadingStr[0]));
                logger.info("conversationId:{}, FlightNearGoQueryTool request:{}, flightApiUrl:{}", conversationId, request, flightNearGoQueryToolUrl);
                post = httpManager.post(flightNearGoQueryToolUrl, request, FlightLowPriceQueryTool.Response.class);
            } else if (mapCity.get(request.arrivalCityName)) {
                messageSender.send(conversationId, I18nUtil.getMessage(conversationId,loadingStr[1]));
                logger.info("conversationId:{}, FlightNearBackQueryTool request:{}, flightApiUrl:{}", conversationId, request, flightNearBackQueryToolUrl);
                post = httpManager.post(flightNearBackQueryToolUrl, request, FlightLowPriceQueryTool.Response.class);
            } else {
                logger.info("conversationId:{}, FlightTimeQueryTool request:{}, flightApiUrl:{}", conversationId, request, flightTimeQueryToolUrl);
                post = httpManager.post(flightTimeQueryToolUrl, request, FlightLowPriceQueryTool.Response.class);
            }
            if (post.queryId() != null) {
                Map<String, Object> hashMap = chatEnvironmentMemory.get(conversationId);
                hashMap.put("queryId", post.queryId());
                hashMap.put("departureCityName", request.departureCityName);
                hashMap.put("arrivalCityName", request.arrivalCityName);
                hashMap.put("departureDate", request.departureDate);
                hashMap.put("backDepartureDate", "");
                chatEnvironmentMemory.add(conversationId, hashMap);
            }
            if (CollectionUtils.isEmpty(post.data())) {
                return post;
            }
            return post.buildResponse();
        } catch (Exception e) {
            logger.error("conversationId:{}, FlightTimeQueryTool request exception:{}", conversationId, e.getMessage());
            return null;
        }
    }

    @Override
    public List<String> before(Object request, ToolContext context) {
        Request rRequest = (Request) request;
        String conversationId = (String) context.getContext().get("conversation_id");
        String[] loadingStr = FlightToolEnum.FLIGHT_TIME_TOOL_LIST.getBefore().split(",");
        if (StringUtils.hasText(rRequest.departureCityName) && StringUtils.hasText(rRequest.arrivalCityName) && StringUtils.hasText(rRequest.departureDate)) {
            String promptMessage = I18nUtil.getMessage(conversationId,loadingStr[0]);
            if (StringUtils.hasText(rRequest.departureTime)) {
                promptMessage = promptMessage + I18nUtil.getMessage(conversationId,loadingStr[1]) + rRequest.departureTime;
            }
            if (StringUtils.hasText(rRequest.arrivalTime)) {
                promptMessage = promptMessage + I18nUtil.getMessage(conversationId,loadingStr[2]) + rRequest.arrivalTime;
            }
            if (promptMessage.length() > I18nUtil.getMessage(conversationId,loadingStr[0]).length()) {
                promptMessage += I18nUtil.getMessage(conversationId,loadingStr[3]);
            }
            promptMessage += I18nUtil.getMessage(conversationId,loadingStr[4]);
            return List.of(FlightMessageUtils.getShowMessage(rRequest.departureCityName, rRequest.arrivalCityName, rRequest.departureDate, null,conversationId), promptMessage);
        }
        return null;
    }

    @Override
    public List<String> after(Object request, ToolContext context, Object response) {
        String conversationId = (String) context.getContext().get("conversation_id");
        FlightLowPriceQueryTool.Response result = (FlightLowPriceQueryTool.Response) response;
        if (response != null && result.data() != null) {
            return List.of(FlightMessageUtils.getToolMessage(result.data().size(),conversationId));
        }
        return null;
    }

    @JsonClassDescription("Query domestic flight input parameters according to time range")
    public record Request(
            @JsonProperty(required = true,
                    value = "departureCityName") @JsonPropertyDescription("departure city") String departureCityName,
            @JsonProperty(required = true,
                    value = "arrivalCityName") @JsonPropertyDescription("arrival city") String arrivalCityName,
            @JsonProperty(required = true,
                    value = "departureDate") @JsonPropertyDescription("departure date, format:yyyy-MM-dd") String departureDate,
            @JsonProperty(value = "departureTime") @JsonPropertyDescription("departure time range, format: HH:mm-HH:mm") String departureTime,
            @JsonProperty(value = "arrivalTime") @JsonPropertyDescription("arrival time range, format: HH:mm-HH:mm") String arrivalTime) {
    }
}
